From 3bba8a3d23f62b52184bb720cdfabbcabf738945 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 17 Mar 2008 11:39:50 +0000 Subject: [PATCH] SVM: handle page faults in emulated instruction fetches Deal with failures in hvm_copy_from_guest_virt when fetching instructions in the various SVM emulation paths. Since we know that the instruction was fetchable by the hardware, we can usually just return from the VMEXIT and try again; whatever caused us to fail will cause the hardware to fail next time and we'll get the correct exit code. Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/svm/emulate.c | 4 +++- xen/arch/x86/hvm/svm/svm.c | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/svm/emulate.c b/xen/arch/x86/hvm/svm/emulate.c index 530ed4606a..cdf0059c99 100644 --- a/xen/arch/x86/hvm/svm/emulate.c +++ b/xen/arch/x86/hvm/svm/emulate.c @@ -117,7 +117,9 @@ int __get_instruction_length_from_list(struct vcpu *v, } else { - inst_copy_from_guest(buffer, svm_rip2pointer(v), MAX_INST_LEN); + if ( inst_copy_from_guest(buffer, svm_rip2pointer(v), MAX_INST_LEN) + != MAX_INST_LEN ) + return 0; buf = buffer; } diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index ba934c1399..e29aeda008 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -943,6 +943,10 @@ static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs) { unsigned int eax, ebx, ecx, edx, inst_len; + inst_len = __get_instruction_length(current, INSTR_CPUID, NULL); + if ( inst_len == 0 ) + return; + eax = regs->eax; ebx = regs->ebx; ecx = regs->ecx; @@ -955,7 +959,6 @@ static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs) regs->ecx = ecx; regs->edx = edx; - inst_len = __get_instruction_length(current, INSTR_CPUID, NULL); __update_guest_eip(regs, inst_len); } @@ -1166,6 +1169,8 @@ static void svm_vmexit_do_hlt(struct vmcb_struct *vmcb, unsigned int inst_len; inst_len = __get_instruction_length(curr, INSTR_HLT, NULL); + if ( inst_len == 0 ) + return 0; __update_guest_eip(regs, inst_len); /* Check for pending exception or new interrupt. */ @@ -1354,6 +1359,8 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) case VMEXIT_VMMCALL: inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL); + if ( inst_len == 0 ) + break; HVMTRACE_1D(VMMCALL, v, regs->eax); rc = hvm_do_hypercall(regs); if ( rc != HVM_HCALL_preempted ) -- 2.30.2